#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <string>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <pthread.h>

#define NUM 2048

void IOService(const int& new_sock)
{
    while (true)
    {
        char buffer[NUM] = {0};
        ssize_t ret = read(new_sock, buffer, sizeof(buffer));
        if (ret > 0)
        {
            std::cout << "client# " << buffer << std::endl;
            std::string echo_string = "hello world";

            write(new_sock, echo_string.c_str(), echo_string.length());
        }
        else if (ret == 0)
        {
            std::cout << "connect close " << std::endl;
            break;
        }
        else
        {
            std::cout << "read error " << std::endl;
            break;
        }
    }
}
void Usage(const std::string &proc)
{
    std::cout << "you can use " << proc << " port" << std::endl;
}

void* handler_request(void* args)
{
    pthread_detach(pthread_self());
    int sock = *(int*)args;
    delete (int*)args;
    IOService(sock);
    close(sock);

    return nullptr;
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        return 1;
    }
    // 1.创建套接字
    int listen_sock = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_sock < 0)
    {
        std::cout << "listen_sock error" << std::endl;
        return 2;
    }
    // 2.bind绑定ip与port
    struct sockaddr_in local;
    local.sin_family = AF_INET;
    local.sin_port = htons(atoi(argv[1]));
    local.sin_addr.s_addr = INADDR_ANY;
    if (bind(listen_sock, (struct sockaddr *)&local, sizeof(local)) < 0)
    {
        std::cout << "bind error" << std::endl;
        return 3;
    }
    // 3.监听套接字
    const int back_log = 5;
    if (listen(listen_sock, back_log) < 0)
    {
        std::cout << "listen error" << std::endl;
        return 4;
    }
    //signal(SIGCHLD, SIG_IGN);
    for (;;)
    {
        // 4.建立连接
        struct sockaddr_in myaddr;
        socklen_t len = sizeof(myaddr);
        int new_sock = accept(listen_sock, (struct sockaddr *)&myaddr, &len);
        if (new_sock < 0)
            continue;
        uint16_t cl_port = ntohs(myaddr.sin_port);
        std::string cl_IP = inet_ntoa(myaddr.sin_addr);
        std::cout << "get a link : " << "[" << cl_IP << "]["<< cl_port << "], new_sock : " <<  new_sock << std::endl;
        
        pthread_t tid;
        int* parm = new int(new_sock);
        pthread_create(&tid, nullptr, handler_request, (void*)parm);
        // pid_t id = fork();
        // if(id < 0)
        //     std::cout << "fork error" << std::endl;
        // else if(id == 0)//child
        // {
        //     // 5.提供服务
        //     close(listen_sock);

        //     if(fork() > 0) exit(0);

        //     IOService(new_sock);
        //     close(new_sock);
        //     exit(0);
        // }
        // else //父进程
        // {
        //     waitpid(id, nullptr, 0);
        //     close(new_sock);
        //     //do nothing
        // }
    }

    return 0;
}